#pragma once

#include "zqdb.h"
#include "zqstr.hpp"
#include "zqdb.pb.h"
#include "mdbdf.hpp"

namespace zqdb {

	template<class TStream>
	void SerializeTableDataToJson(TStream& os, const char* db, const char* tb, MDB_FIELD* attr, size_t attr_num, const char* data)
	{
		for (size_t i = 0; i < attr_num; i++)
		{
			const char* name = MDBTableGetFieldName(db, tb, i);
			if (!name) {
				break;
			}
			os << (i == 0 ? "\"" : ",\"") << name << "\":";
			char buf[1024] = { 0 };
			size_t buflen = 1024;
			char* sbuf = buf;
			char** val = &sbuf;
			size_t* sz = &buflen;
			mdb::FieldOp::GetValueAsStr(data, attr + i, 1, val, sz, nullptr);
			switch (attr[i].type)
			{
			case MDB_FIELD_TYPE_BYTE:
			case MDB_FIELD_TYPE_INT16:
			case MDB_FIELD_TYPE_UINT16:
			case MDB_FIELD_TYPE_INT32:
			case MDB_FIELD_TYPE_UINT32:
			case MDB_FIELD_TYPE_INT64:
			case MDB_FIELD_TYPE_UINT64:
			case MDB_FIELD_TYPE_FLOAT:
			case MDB_FIELD_TYPE_DOUBLE: {
				os << buf;
			} break;
			case MDB_FIELD_TYPE_CHAR:
			case MDB_FIELD_TYPE_STRING: {
				os << "\"" << buf << "\"";
			} break;
			default: {
			} break;
			}
		}
	}

	template<class TStream>
	void BuildJsonFromTableDataInfo(TStream& os, const char* db, const char* tb, HMDB hdb, HMTABLE htb, const char* data)
	{
		size_t attr_sz = 0;
		MDB_FIELD* attr = (MDB_FIELD*)MDBTableGetAttr(hdb, htb, &attr_sz);
		size_t attr_num = attr_sz / sizeof(MDB_FIELD);
		os << "{";
		SerializeTableDataToJson(os, db, tb, attr, attr_num, data);
		os << "}";
	}

	template<class TStream>
	void BuildJsonFromTableInfo(TStream& os, HMDB hdb, HMTABLE htb)
	{
		auto db_name = MDBGetName(hdb);
		auto tb_name = MDBTableGetName(hdb, htb);
		size_t attr_sz = 0;
		MDB_FIELD* attr = (MDB_FIELD*)MDBTableGetAttr(hdb, htb, &attr_sz);
		size_t attr_num = attr_sz / sizeof(MDB_FIELD);
		os << "{\n";
		size_t count = MDBTableGetValueCount(hdb, htb, nullptr);
		for (size_t i = 0; i < attr_num; i++)
		{
			os << "\"" << MDBTableGetFieldName(db_name, tb_name, i) << "\":[";
			for (size_t j = 0; j < count; j++)
			{
				char buf[1024] = { 0 };
				size_t buflen = 1024;
				char* sbuf = buf;
				char** val = &sbuf;
				size_t* sz = &buflen;
				MDBTableGetFieldValueAsStr(hdb, htb, attr + i, 1, j, 1, &val, &sz, nullptr);
				switch (attr[i].type)
				{
				case MDB_FIELD_TYPE_BYTE:
				case MDB_FIELD_TYPE_INT16:
				case MDB_FIELD_TYPE_UINT16:
				case MDB_FIELD_TYPE_INT32:
				case MDB_FIELD_TYPE_UINT32:
				case MDB_FIELD_TYPE_INT64:
				case MDB_FIELD_TYPE_UINT64:
				case MDB_FIELD_TYPE_FLOAT:
				case MDB_FIELD_TYPE_DOUBLE: {
					os << buf;
				} break;
				case MDB_FIELD_TYPE_CHAR:
				case MDB_FIELD_TYPE_STRING: {
					os << "\"" << buf << "\"";
				} break;
				default: {
				} break;
				}
				if (j < count - 1) {
					os << ",";
				}
			}
			if (i < attr_num - 1) {
				os << "],\n";
			}
			else {
				os << "]\n";
			}
		}
		os << "}";
	}

}
